﻿#include <iostream>
#include <vector>
#include <windows.h>
#include <Thread>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
using namespace std;
// ■  □

#define M 15
#define N 26
#define X_begin 20
#define Y_begin 4

#define S_X_begin X_begin + 2
#define S_X_end X_begin + M * 2 - 2

#define S_Y_begin Y_begin + 1
#define S_Y_end  Y_begin + N - 2 

#define SORCE_WORD_X 0
#define SORCE_WORD_Y 2


enum TypeShape
{
	lS,
	_S,
	wS,
	zS,
	LS,
	JS,
	MS
};

struct Shape
{
	int x1, y1;
	int x2, y2;
	int x3, y3;
	int x4, y4;
	TypeShape tpye;

	// 左转90度（逆时针）
	void rotateLeft()
	{
		// Step 1: 计算形状的几何中心（基于网格对齐后的坐标）
		int centerX = ((x1 + x2 + x3 + x4) / 4) & ~0x1; // 强制中心点x为偶数
		int centerY = (y1 + y2 + y3 + y4) / 4;

		// Step 2: 应用旋转公式（适配2:1终端比例）
		rotatePoint(x1, y1, centerX, centerY, 1);
		rotatePoint(x2, y2, centerX, centerY, 1);
		rotatePoint(x3, y3, centerX, centerY, 1);
		rotatePoint(x4, y4, centerX, centerY, 1);

		// Step 3: 严格对齐到网格（确保所有x坐标为偶数）
		alignToGrid();
	}

	// 右转90度（顺时针）
	void rotateRight()
	{
		int centerX = ((x1 + x2 + x3 + x4) / 4) & ~0x1;
		int centerY = (y1 + y2 + y3 + y4) / 4;

		rotatePoint(x1, y1, centerX, centerY, -1);
		rotatePoint(x2, y2, centerX, centerY, -1);
		rotatePoint(x3, y3, centerX, centerY, -1);
		rotatePoint(x4, y4, centerX, centerY, -1);

		alignToGrid();
	}
	// 提供下降函数
	void DownPerOneSec()
	{
		y1++;
		y2++;
		y3++;
		y4++;
	}
	void TurnLeft()
	{
		x1 -= 2;
		x2 -= 2;
		x3 -= 2;
		x4 -= 2;
	}
	void TurnRight()
	{
		x1 += 2;
		x2 += 2;
		x3 += 2;
		x4 += 2;
	}

	void Update(shared_ptr<Shape> p)
	{
		x1 = p->x1;
		x2 = p->x2;
		x3 = p->x3;
		x4 = p->x4;
		y1 = p->y1;
		y2 = p->y2;
		y3 = p->y3;
		y4 = p->y4;
	}


	// 在边界 返回false
	// 非边界 返回true
	bool LeftBorderCheck()
	{
		if (GetMinX() < S_X_begin)
			return false;
		return true;
	}

	bool RightBorderCheck()
	{
		if (GetMaxX() > S_X_end - 2)
			return false;
		return true;
	}

	// 未达到底部 true
	// >= 底部false
	bool BottomCheck()
	{
		if (GetMaxY() >= S_Y_end)
			return false;
		return true;
	}
	
	bool TopCheck()
	{
		if (GetMinY() < S_Y_begin)
			return false;
		return true;
	}

	bool BeginLocation()
	{
		if (GetMinX() >= S_X_begin && GetMaxX() < S_X_end)
			return true;
		else
			return false;
	}

	int GetMaxX()
	{
		return max(max(x1, x2), max(x3, x4));
	}

	int GetMinX()
	{
		return min(min(x1, x2), min(x3, x4));
	}

	int GetMinY()
	{
		return min(min(y1, y2), min(y3, y4));

	}

	int GetMaxY()
	{
		return max(max(y1, y2), max(y3, y4));
	}

	// 在边界 返回false
	// 非边界 返回true
	virtual void SetXVal(int x)
	{};

private:
	// 旋转单个点（direction=1右转，direction=-1左转）
	void rotatePoint(int& x, int& y, int centerX, int centerY, int direction) {
		// 转换为相对中心的坐标（考虑2:1比例）
		float dx = (x - centerX) / 2.0f; // 水平单位是1/2字符宽度
		float dy = (y - centerY);

		// 应用旋转矩阵（无浮点误差）
		float new_dx, new_dy;
		if (direction == 1) { // 右转90度
			new_dx = dy;
			new_dy = -dx;
		}
		else { // 左转90度
			new_dx = -dy;
			new_dy = dx;
		}

		// 转换回实际坐标（避免舍入误差）
		x = centerX + roundEven(new_dx * 2); // 关键：保证结果为偶数
		y = centerY + round(new_dy);
	}

	// 专用对齐函数：确保所有x坐标为偶数
	void alignToGrid() {
		x1 = (x1 + (x1 & 0x1)) & ~0x1; // 奇则+1，偶则不变
		x2 = (x2 + (x2 & 0x1)) & ~0x1;
		x3 = (x3 + (x3 & 0x1)) & ~0x1;
		x4 = (x4 + (x4 & 0x1)) & ~0x1;
	}

	// 专用舍入函数：保证结果为偶数
	int roundEven(float value) {
		int intVal = static_cast<int>(std::round(value));
		return (intVal + (intVal & 0x1)) & ~0x1; // 强制偶数
	}
};

struct lShape : public Shape
{
	// x1,y1最上面     上到下
	lShape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x1, y2 = y + 1;
		x3 = x1, y3 = y + 2;
		x4 = x1, y4 = y + 3;
		tpye = t;
	}
	void SetXVal(int x)
	{
		x1 = x;
		x2 = x1;
		x3 = x1;
		x4 = x1;
	}
};

struct _Shape : public Shape
{
	// 最左侧 x1,y1    左到右
	_Shape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x + 2, y2 = y;
		x3 = x + 4, y3 = y;
		x4 = x + 6, y4 = y;
		tpye = t;
	}

	void SetXVal(int x)
	{
		x1 = x;
		x2 = x + 2;
		x3 = x + 4;
		x4 = x + 6;
	}
};

struct wShape : public Shape
{
	// x1,y1 最上面  上，左到右
	wShape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x1 - 2, y2 = y + 1;
		x3 = x1, y3 = y + 1;
		x4 = x1 + 2, y4 = y + 1;
		tpye = t;

	}

	void SetXVal(int x)
	{
		x1 = x;
		x2 = x1 - 2;
		x3 = x1;
		x4 = x1 + 2;
	}

};

struct zShape : public Shape
{
	//x1 ,y1 左上角
	zShape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x1 + 2, y2 = y;
		x3 = x2, y3 = y2 + 1;
		x4 = x3 + 2, y4 = y3;
		tpye = t;
	}

	void SetXVal(int x)
	{
		x1 = x;
		x2 = x1 + 2;
		x3 = x2;
		x4 = x3 + 2;
	}

};

struct LShape : public Shape
{
	// x1,x2 最上面
	LShape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x, y2 = y + 1;
		x3 = x, y3 = y + 2;
		x4 = x3 + 2, y4 = y + 2;
		tpye = t;
	}
	void SetXVal(int x)
	{
		x1 = x;
		x2 = x;
		x3 = x;
		x4 = x3 + 2;
	}

};

struct JShape : public Shape
{
	// x1,x2 最上面
	JShape(int x, int y, TypeShape t)
	{
		x1 = x, y1 = y;
		x2 = x, y2 = y + 1;
		x3 = x, y3 = y + 2;
		x4 = x3 - 2, y4 = y + 2;
		tpye = t;
	}

	void SetXVal(int x)
	{
		x1 = x;
		x2 = x;
		x3 = x;
		x4 = x3 - 2;
	}
};

class SimpleFactory
{
public:
	static std::shared_ptr<Shape> CreateShape(TypeShape ts, int x, int y)
	{
		if (ts == TypeShape::lS)
		{
			return make_shared<lShape>(x, y, ts);
		}
		else if (ts == TypeShape::_S)
		{
			return make_shared<_Shape>(x, y, ts);
		}
		else if (ts == TypeShape::wS)
		{
			return make_shared<wShape>(x, y, ts);
		}
		else if (ts == TypeShape::zS)
		{
			return make_shared<zShape>(x, y, ts);
		}
		else if (ts == TypeShape::LS)
		{
			return make_shared<LShape>(x, y, ts);
		}
		else if (ts == TypeShape::JS)
		{
			return make_shared<JShape>(x, y, ts);
		}
		return shared_ptr<Shape>();
	}
};

class Tretris
{
public:

	void gotoxy(int x, int y)
	{
		COORD pos; //位置 COORD是库里定义的类型。
		HANDLE hOutput;
		pos.X = x;//水平方向
		pos.Y = y;//垂直方向
		hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		//获取缓冲区中的数据，地址赋值给句柄
		SetConsoleCursorPosition(hOutput, pos);
		/*定位光标位置的函数，坐标为GetStdHandle（）返回标准的输出的句柄，
		也就是获得输出屏幕缓冲区的句柄，并赋值给对象 pos*/

		/*隐藏光标操作 */
		CONSOLE_CURSOR_INFO cursor;
		cursor.bVisible = FALSE;
		cursor.dwSize = sizeof(cursor);
		SetConsoleCursorInfo(hOutput, &cursor);
	}

	Tretris()
	{
		arrive = true;
		InitWall();
		srand((unsigned int)time(nullptr));
		DrawWall();
		sorce = 0;
		gotoxy(SORCE_WORD_X, SORCE_WORD_Y);
		cout << "Sorce: " << sorce;
		int h = 0 ;
		gotoxy(S_X_end + 5, S_Y_begin + h);
		cout << "左移: a,←" << endl;
		h += 2;
		gotoxy(S_X_end + 5, S_Y_begin + h);
		cout << "右移: d,→" << endl;
		h += 2;
		gotoxy(S_X_end + 5, S_Y_begin + h);
		cout << "快速下落: s,↓" << endl;
		h += 2;
		gotoxy(S_X_end + 5, S_Y_begin + h);
		cout << "左转: j" << endl;
		h += 2;

		gotoxy(S_X_end + 5, S_Y_begin + h);
		cout << "右转: k" << endl;



	}

	void Process()
	{
		char press_key;
		int k = 1;
		clock_t last_time = clock();
		const clock_t interval = clock_t(200);  // 间隔1秒（CLOCKS_PER_SEC=1000时为1秒）
		while (true)
		{
			clock_t cur_time = clock();
			if (arrive == true)
			{
				FirstShape();
				DrawDropShape();
			}
			bool fast_flag = false;
			// 检测键盘是否有按键按下
			if (_kbhit())
			{
				press_key = _getch();
				if (press_key == 'A' || press_key == 'a' || press_key == 75)// 左
				{
					shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
					ClearPreShape(pre_Shape);
					cur_Shape->TurnLeft();

					if (!cur_Shape->LeftBorderCheck() ||  
						map[cur_Shape->y4 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
						map[cur_Shape->y3 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
						map[cur_Shape->y2 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
						map[cur_Shape->y1 - Y_begin][cur_Shape->x1 - X_begin] == 2)
					{
						cur_Shape->Update(pre_Shape);
					}
					DrawDropShape();
					last_time = cur_time;
				}
				else if (press_key == 'D' || press_key == 'd' || press_key == 77) // 右
				{
					shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
					ClearPreShape(pre_Shape);
					cur_Shape->TurnRight();

					if ( !cur_Shape->RightBorderCheck() ||
						map[cur_Shape->y4 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
						map[cur_Shape->y3 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
						map[cur_Shape->y2 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
						map[cur_Shape->y1 - Y_begin][cur_Shape->x1 - X_begin] == 2)
					{
						cur_Shape->Update(pre_Shape);
					}
					DrawDropShape();
					last_time = cur_time;
				}
				else if (press_key == 'J' || press_key == 'j') // 左转
				{
					shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
					ClearPreShape(pre_Shape);
					cur_Shape->rotateLeft();
					if (!cur_Shape->LeftBorderCheck() || !cur_Shape->RightBorderCheck() || 
						!cur_Shape->BottomCheck() || !cur_Shape->TopCheck() ||
						map[cur_Shape->y4 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
						map[cur_Shape->y3 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
						map[cur_Shape->y2 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
						map[cur_Shape->y1 - Y_begin][cur_Shape->x1 - X_begin] == 2)

					{
						cur_Shape->Update(pre_Shape);
					}
					DrawDropShape();
					last_time = cur_time;
				}
				else if (press_key == 'K' || press_key == 'k') // 右转
				{
					shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
					ClearPreShape(pre_Shape);
					cur_Shape->rotateRight();
					if (!cur_Shape->LeftBorderCheck() || !cur_Shape->RightBorderCheck() || 
						!cur_Shape->BottomCheck() || !cur_Shape->TopCheck() ||
						map[cur_Shape->y4 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
						map[cur_Shape->y3 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
						map[cur_Shape->y2 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
						map[cur_Shape->y1 - Y_begin][cur_Shape->x1 - X_begin] == 2)
					{
						cur_Shape->Update(pre_Shape);
					}
					DrawDropShape();
					last_time = cur_time;
				}
				else if (press_key == 'S' || press_key == 's' || press_key == 80) // 加速下落
				{
					shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
					ClearPreShape(pre_Shape);
					fast_flag = true;
					DownFast();
					DrawDropShape();
					last_time = cur_time;

				}
			}
			// 每隔 interval 俄罗斯方块进行下落
			if (cur_time - last_time >= interval)
			{
				shared_ptr<Shape> pre_Shape = make_shared<Shape>(*cur_Shape);
				ClearPreShape(pre_Shape);

				if(!fast_flag)
					cur_Shape->DownPerOneSec();
				
				DrawDropShape();
				last_time = cur_time;
			}


			
			// y --> N ,x --> M
			// 到达底部，或者下方有图块
			if (!cur_Shape->BottomCheck() ||
				map[cur_Shape->y4 + 1 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
				map[cur_Shape->y3 + 1 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
				map[cur_Shape->y2 + 1 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
				map[cur_Shape->y1 + 1 - Y_begin][cur_Shape->x1 - X_begin] == 2)
			{
				arrive = true;
				// 更新map
				map[cur_Shape->y1 - Y_begin][cur_Shape->x1 - X_begin] = 2;
				map[cur_Shape->y2 - Y_begin][cur_Shape->x2 - X_begin] = 2;
				map[cur_Shape->y3 - Y_begin][cur_Shape->x3 - X_begin] = 2;
				map[cur_Shape->y4 - Y_begin][cur_Shape->x4 - X_begin] = 2;
				//循环检测最后一行 
				int line = -1;
				while (CheckLine(line))
				{
					sorce += M - 2;
					gotoxy(SORCE_WORD_X, SORCE_WORD_Y);
					cout << "Sorce: " << sorce;


					ClearLastLine();
					for (int i = 2; i < M * 2 - 2; i += 2)
					{
						map[line][i] = 0;
					}
					TotalDown(line);
					DrawMap();
				}
			}
			else
				arrive = false;

		}
	}

private:

	void Over()
	{
		system("cls");
		gotoxy(4, 4);
		cout << R"(
				   _____          __  __ ______    ______      ________ _____  
				  / ____|   /\   |  \/  |  ____|  / __ \ \    / /  ____|  __ \ 
				 | |  __   /  \  | \  / | |__    | |  | \ \  / /| |__  | |__) |
				 | | |_ | / /\ \ | |\/| |  __|   | |  | |\ \/ / |  __| |  _  / 
				 | |__| |/ ____ \| |  | | |____  | |__| | \  /  | |____| | \ \ 
				  \_____/_/    \_\_|  |_|______|  \____/   \/   |______|_|  \_\
				)" << endl;

	}

	void DownFast()
	{
		while (cur_Shape->BottomCheck() &&
			map[cur_Shape->y4 + 1 - Y_begin][cur_Shape->x4 - X_begin] != 2 &&
			map[cur_Shape->y3 + 1 - Y_begin][cur_Shape->x3 - X_begin] != 2 &&
			map[cur_Shape->y2 + 1 - Y_begin][cur_Shape->x2 - X_begin] != 2 &&
			map[cur_Shape->y1 + 1 - Y_begin][cur_Shape->x1 - X_begin] != 2)
		{
			cur_Shape->DownPerOneSec();
		}

	}

	// 清除最后一行
	void ClearLastLine()
	{
		for (int i = 0; i < M * 2 - 4; i += 2)
		{
			//map[N - 1][i]
			gotoxy(i + S_X_begin, S_Y_end);
			cout << "  ";
		}
	}

	void DrawMap()
	{
		for (int i = N - 2; i > 0; i--)
		{
			for (int j = 2; j < M * 2 - 2; j += 2)
			{
				gotoxy(X_begin + j, Y_begin + i);

				if (map[i][j] == 2)
				{
					cout << "□";
				}
				else
				{
					cout << "  ";
				}
			}
		}
	}

	// 第一块图形
	void FirstShape()
	{
		down_x = 1;
		cur_Shape = SimpleFactory::CreateShape((TypeShape)(rand() % MS), down_x, S_Y_begin);
		while (!cur_Shape->BeginLocation() || cur_Shape->x1 % 2 == 1)
		{
			down_x = S_X_begin + (rand() % (N * 2));
			cur_Shape->SetXVal(down_x);
		}
		//gotoxy(0, i++);
		//cout << "down_x = " << down_x;
		if (map[cur_Shape->y4 + 1 - Y_begin][cur_Shape->x4 - X_begin] == 2 ||
			map[cur_Shape->y3 + 1 - Y_begin][cur_Shape->x3 - X_begin] == 2 ||
			map[cur_Shape->y2 + 1 - Y_begin][cur_Shape->x2 - X_begin] == 2 ||
			map[cur_Shape->y1 + 1 - Y_begin][cur_Shape->x1 - X_begin] == 2)
		{
			DrawDropShape();
			Sleep(500);
			Over();
			exit(0);
		}

	}

	void ClearPreShape(const shared_ptr<Shape>& pre)
	{
		gotoxy(pre->x1, pre->y1);
		cout << "  ";

		gotoxy(pre->x2, pre->y2);
		cout << "  ";

		gotoxy(pre->x3, pre->y3);
		cout << "  ";

		gotoxy(pre->x4, pre->y4);
		cout << "  ";
		fflush(stdout);
	}

	void DrawDropShape()
	{
		gotoxy(cur_Shape->x1, cur_Shape->y1);
		cout << "□";

		gotoxy(cur_Shape->x2, cur_Shape->y2);
		cout << "□";

		gotoxy(cur_Shape->x3, cur_Shape->y3);
		cout << "□";

		gotoxy(cur_Shape->x4, cur_Shape->y4);
		cout << "□";
		fflush(stdout);
	}

	// 整体下移
	void TotalDown(int line)
	{
		// N - 1 是墙
		for (int i = line; i > 0; i--)
		{
			for (int j = 2; j < M * 2; j += 2)
			{
				if (map[i][j] == 2)
				{
					map[i + 1][j] = map[i][j];
					map[i][j] = 0;
				}
			}
		}
	}

	// 检查行
	bool CheckLine(int& line)
	{
		bool flag;
		for (int j = N - 2; j > 0; j--)
		{
			if (j == 17)
				int a = 0;
			flag = false;
			for (int i = 2; i < M * 2 - 2; i += 2)
			{
				if (map[j][i] != 2)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				line = j;
				return true;
			}

		}

		return false;
	}

	void InitWall()
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M * 2; j++)
			{
				if (i == 0 || j == 0 || i == N - 1 || j == M * 2 - 2)
				{
					map[i][j] = 1;
				}
			}
		}
	}

	void DrawWall()
	{
		gotoxy(X_begin, Y_begin);
		for (int i = 0; i < N; i++)
		{
			gotoxy(X_begin, Y_begin + i);
			for (int j = 0; j < M * 2; j += 2)
			{
				if (i == 0 || i == N - 1 || j == 0 || j == M * 2 - 2)
				{
					cout << "■";
				}
				else
				{
					cout << "  ";
				}
			}
			cout << endl;
		}
	}

private:
	// 0为空缺，1为墙壁，  2为方块
	int map[N][M * 2] = { 0 };
	int down_x; // 随机初始点 x坐标
	shared_ptr<Shape> cur_Shape; // 当前下落的图块
	bool arrive;
	int sorce;
};

int main()
{
	Tretris tre;
	tre.Process();
	tre.gotoxy(0, 26);
	return 0;
}
